package com.tom.demo.service.approvalsettings.impl;

import cn.hutool.core.lang.Snowflake;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tom.demo.common.entity.OaProcessTemplate;
import com.tom.demo.common.enumeration.FieldTypeEnum;
import com.tom.demo.common.enumeration.ResponseEnum;
import com.tom.demo.common.exception.CustomException;
import com.tom.demo.common.exception.ServiceException;
import com.tom.demo.common.response.Result;
import com.tom.demo.common.utils.SecurityUtils;
import com.tom.demo.component.MinioComponent;
import com.tom.demo.mapper.OaProcessTemplateMapper;
import com.tom.demo.service.approvalsettings.OaProcessTemplateService;
import com.tom.demo.vo.OaProcessTemplateVo;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

/**
* @author Admin
* @description 针对表【oa_process_template(审批模板表)】的数据库操作Service实现
* @createDate 2025-03-19 23:33:16
*/
@Slf4j
@Service
public class OaProcessTemplateServiceImpl implements OaProcessTemplateService {

    @Resource
    private OaProcessTemplateMapper oaProcessTemplateMapper;

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private Snowflake snowflake;

    @Resource
    private MinioComponent minioComponent;

    @Value("${bucketName}")
    private String bucketName;

    @Override
    public Result list(Integer page, Integer pageSize, OaProcessTemplate oaProcessTemplate) {
        PageHelper.startPage(page,pageSize);
        List<OaProcessTemplateVo> oaProcessTemplateVos = oaProcessTemplateMapper.list(oaProcessTemplate);
        PageInfo<OaProcessTemplateVo> pageInfo = new PageInfo<>(oaProcessTemplateVos);
        return Result.success(pageInfo);
    }

    @Override
    public Result save(OaProcessTemplate oaProcessTemplate) {
        oaProcessTemplate.setId(snowflake.nextIdStr());
        oaProcessTemplate.setIsDeleted(FieldTypeEnum.IsDelete.NOT_DELETE.getStatus());
        oaProcessTemplate.setStatus(FieldTypeEnum.status.NOT_RELEASE.getRelease());
        oaProcessTemplate.setCreateBy(SecurityUtils.getLoginUserName());
        oaProcessTemplate.setCreateTime(new Date());
        int row = oaProcessTemplateMapper.insert(oaProcessTemplate);
        return row > 0?Result.success():Result.error("保存模板失败");
    }

    @Override
    public Result deleteById(String id) {
        OaProcessTemplate oaProcessTemplate = oaProcessTemplateMapper.findById(id);
        oaProcessTemplate.setIsDeleted(FieldTypeEnum.IsDelete.IS_DELETE.getStatus());
        oaProcessTemplate.setUpdateBy(SecurityUtils.getLoginUserName());
        oaProcessTemplate.setUpdateTime(new Date());
        int row = oaProcessTemplateMapper.updateById(oaProcessTemplate);
        return row > 0?Result.success():Result.error("删除模板失败");
    }

    @Override
    @DSTransactional
    public Result deploymentProcess(String id) {
        //现根据id查询出来当前模板数据
        OaProcessTemplate oaProcessTemplate = oaProcessTemplateMapper.findById(id);
        //根据模板数据去activiti中部署流程，因为我们的 .bpmn20.xml文件存储在oaProcessTemplate这个当中
        //获取到bpmn20.xml文件在minio中的地址
        String processDefinitionPath = oaProcessTemplate.getProcessDefinitionPath();
        //根据这个minio地址，我们去获取到文件的流
        try {
            //这里只能用文件 桶的名字 + 文件名字 去获取
            //完整的地址是: http://122.51.49.25:19000/component-management-back-api/18f7390901c34823a147b0f530166f2c.xml
            //我们需要的是: 18f7390901c34823a147b0f530166f2c.xml
            String fileName = processDefinitionPath.substring(processDefinitionPath.lastIndexOf('/') + 1);
            InputStream inputStream = minioComponent.downloadFile(bucketName, fileName);
            //对应的是act_re_deployment表，这个表里面的只有id和name有点用，其他的都没有用
//            Deployment deployment = repositoryService.createDeployment()
//                    .addClasspathResource("processes/WorkOvertime.bpmn20.xml")
//                    .addClasspathResource("processes/WorkOvertime.png")
//                    .name(oaProcessTemplate.getTemplateName())//请假
//                    .deploy();

            String resourceName = oaProcessTemplate.getTemplateName()+".bpmn20.xml";
            //开始部署，这个部署操作走完之后，其实会两张主要的表都会收到影响的 一个是 act_re_deployment和act_re_procdef
            Deployment deployment = repositoryService.createDeployment()
                                            .addInputStream(resourceName,inputStream)
                                            .name(oaProcessTemplate.getTemplateName())
                                            .deploy();

            //查询所有定义的流程
            //List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().list();
            // 根据部署的id获取 获取到指定流程定义Key，这个key在我们启动流程的时候，需要使用到，非常重要,这里我们只获取版本最新的一条即可
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(deployment.getId()).latestVersion().singleResult();
            //修改为已经发布的状态
            oaProcessTemplate.setStatus(FieldTypeEnum.status.IS_RELEASE.getRelease());
            oaProcessTemplate.setProcessDefinitionKey(processDefinition.getKey());
            oaProcessTemplateMapper.updateById(oaProcessTemplate);
            //跟新模板信息
            return Result.success();
        } catch (Exception e) {
            log.error("从minio中获取bpmn20.xml文件失败！！！{}",e.getMessage());
            throw new CustomException(ResponseEnum.SERVER_ERROR);
        }

    }

    @Override
    public Result processDefinitionKey(String processDefinitionKey) {
        OaProcessTemplate oaProcessTemplate = oaProcessTemplateMapper.findByProcessDefinitionKey(processDefinitionKey);
        return Result.success(oaProcessTemplate);
    }
}




